package io.gitee.minelx.commontools.factor;

import java.io.Closeable;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;

public interface CloseableIterator<E> extends Iterator<E>, AutoCloseable {
    @Override
    boolean hasNext();

    @Override
    E next();

    @Override
    void close();

    static <E> CloseableIterator<E> of(Iterator<E> iterator,
                                       Closeable closeable) {
        return new CloseableIterator<E>() {
            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public E next() {
                return iterator.next();
            }

            @Override
            public void close() {
                try {
                    closeable.close();
                } catch (IOException e) {
                    throw new RuntimeException("error while closing " + closeable + ".", e);
                }
            }
        };
    }

    static <E> CloseableIterator<E> fromIterator(Iterator<E> iterator) {
        return new CloseableIterator<E>() {
            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public E next() {
                return iterator.next();
            }

            @Override
            public void close() {
                // do nothing
            }
        };
    }

    static <E> CloseableIterator<E> empty() {
        return CloseableIterator.fromIterator(new Iterator<E>() {
            @Override
            public boolean hasNext() {
                return false;
            }

            @Override
            public E next() {
                throw new NoSuchElementException("CloseableIterator.empty iterator has no element to fetch.");
            }
        });
    }
}
